第 28 天 !
倒數 3 天!
當我們道路都打通後,我們要開始想要傳什麼資料進去,
首先,我們要確定要放在 redux store
的資料是什麼?
通常,我們會把我們整個專案都會用到的資料放入到 store
裡,
所以,我們先把 todoList
的資料移入到 todoReducer
const initState = {
list: [],
};
export default function todoReducer(state = initState, action) {
return state;
}
我們會先設定好 initState
,並且把它當作這個 todoReducer state
的初始值,
最後 return
,這樣我們就把我們的 todoList
保存在 store
裡了
再來我們需要從 mapStateToProps
拿到我們的 todoList
const mapStateToProps = ({ todo }) => {
return {
todo,
};
};
再來導入到 ToDoList Component,
function ToDoList({ todo, changeItemStatus }) {
const { list } = todo;
return (
<FlatList
data={list}
renderItem={({ item, index, separators }) => {
const isEven = index % 2 === 0;
const isDone = item.status === 'done';
return (
<ToDoItem
isEven={isEven}
isDone={isDone}
text={item.text}
onPress={changeItemStatus}
/>
);
}}
keyExtractor={(item) => item.id}
/>
);
}
這樣,我們就已經從 store
取出 todoList
給 component
當我們已經取得資料後,我們需要去設定 action
,讓我們可以去操控我們的資料,
action
都是根據需求去設定的,
針對 todoList
需求如下:
我們在根目錄建立 actions
資料夾,並在底下建立兩個檔案,
types
是專門放置 action type
, creators
就是放置 action creator
,
export const INSERT_TODO = 'INSERT_TODO';
export const CHANGE_TODO_STATUS = 'CHANGE_TODO_STATUS';
export const ALL_TODO_COMPLETE = 'ALL_TODO_COMPLETE';
action type , 通常會用全部大寫的方式表示,內容跟變數名稱會是一致的
import { ALL_TODO_COMPLETE, CHANGE_TODO_STATUS, INSERT_TODO } from './types';
export const insertToDoAction = (payload) => {
return {
type: INSERT_TODO,
payload,
};
};
export const changeToDoStatusAction = (payload) => {
return {
type: CHANGE_TODO_STATUS,
payload,
};
};
export const completeAllAction = () => {
return {
type: ALL_TODO_COMPLETE,
};
};
再來,我們到 todoReducer
設定我們的 action
動作,
const initState = {
list: [],
};
const insertToDo = (state, item) => {
return {
...state,
list: [...state.list, item],
};
};
const changeToDoStatus = (state, { id }) => {
const { list } = state;
const index = list.findIndex((item) => item.id === id);
const nowItem = list[index];
const newStatus = nowItem.status === 'done' ? 'not done' : 'done';
list[index] = {
...nowItem,
status: newStatus,
};
return {
...state,
list: [...list],
};
};
const allToDoComplete = (state) => {
return {
...state,
list: state.list.map((item) => {
return {
...item,
status: 'done',
};
}),
};
};
export default function todoReducer(state = initState, { type, payload }) {
switch (type) {
case INSERT_TODO:
return insertToDo(state, payload);
case CHANGE_TODO_STATUS:
return changeToDoStatus(state, payload);
case ALL_TODO_COMPLETE:
return allToDoComplete(state);
default:
return state;
}
}
這時候,就把從 App component
的邏輯遷到 todoReducer
裡,
我們移入到 Header component
,
現在來設定 mapDispatchToProps
,
假如沒有什麼特別要設定的,
我們可以直接把 action creator
拿來用就好
const mapDispatchToProps = {
insertToDoAction,
};
在 Header component
用 insertToDoAction
取代 createToDoItem
onAddButtonPress = () => {
const { inputValue } = this.state;
const item = {
id: new Date().getTime(),
text: inputValue,
status: 'not done',
};
this.setState(() => {
return {
inputValue: '',
};
});
this.props.insertToDoAction(item);
};
Complete All Button
的 completeAllAction
取代 handleCompleteAll
<FeatureButton text={'Complete All'} onPress={this.props.completeAllAction} />
再來到 ToDoList component
const mapDispatchToProps = {
changeToDoStatusAction,
};
<ToDoItem
isEven={isEven}
isDone={isDone}
text={item.text}
onPress={() => changeToDoStatusAction(item.id)}
/>
這樣就大功告成啦